const request = require('superagent');
require('superagent-proxy')(request);
const MongoClient = require('mongodb').MongoClient;
const random_name = require('node-random-name');
const fs = require('fs');
const path = require('path');
const exec = require('child_process').exec;
const YM = require('./ym');
const mongo = require('../app/lib/mongo');
const ip = '120.24.218.74:27017';
const writeFile = async(path, data)=>{
    return new Promise( (resolve, reject) =>{
        fs.writeFile(path, data, (err, writtrn, string)=>{
            if(err)return reject(err);
            resolve(string);
        })
    })
};
const sleep = (time)=>{
    return new Promise( (resolve, reject) =>{
        setTimeout(function(){resolve(null)}, time * 1000)
    })
};
const generateCookiesString = (array)=>{
    let arr = [];
    for(let co of array){
        let cookie = co.split(";");
        if(cookie[0].indexOf("delete")<0)arr.push(cookie[0])
    }
    return arr.join("; ")
};
const randomString = function(len = 16) {
    var chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    var res = "";
    for (var i = 0; i < len; i++) {
        var id = Math.ceil(Math.random() * 35);
        res += chars[id];
    }
    return res;
};
const waitForCode = function (path){
    return new Promise(async (resolve, reject) => {
        exec(`start ${path}`);
        process.stdout.write(`请打开 ${path} 查看验证码并输入\n`);
        process.stdout.write(`请输入\n`);
        process.stdin.resume();
        process.stdin.setEncoding('utf-8');
        process.stdin.once('data', async (chunk) => {
            try{
                chunk = chunk.replace(/(\n|\r|\s)/g, '');
                resolve(chunk);
            }catch(e){
                console.error(e);
                return await waitForCode(path)
            }
        });
    });
};
const getValidateCode = async(tel = null)=>{
    let pngPath = path.join(__dirname, 'tmp', `${randomString()}.png`);
    try{
        //获取验证码
        let header = {
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
        };
        let indexReq = await request.get('http://web.http.cnapi.cc/core/api/verify').set(header);
        await writeFile(pngPath, indexReq.body);
        let validateCode = await waitForCode(pngPath);
        if(validateCode.length === 4){
            header.cookie = generateCookiesString(indexReq.headers['set-cookie']);
            let ym51;
            if(!tel){
                ym51 = new YM();
                tel = await ym51.getTel();
            } else {
                ym51 = new YM(tel);
            }

            console.log("开始获取手机验证码");
            let jsonCallback = `jQuery${randomString()}_${new Date().getTime()}`;
            let telCode = await request.get(`http://web.http.cnapi.cc/index/users/get_phone_code?jsonpcallback=${jsonCallback}&phone=${tel}&type=reg&reg_verfy=${validateCode}&_=${new Date().getTime()}`).set(header);
            let reg = new RegExp(`^${jsonCallback}\\("(\\S+)"\\)$`);
            let telCodeCallbackBody = telCode.text.match(reg) ? JSON.parse(telCode.text.match(reg)[1].replace(/\\"/g,"\"")) : {};
            console.log('telCodeCallbackBody', telCodeCallbackBody.msg);
            if(telCodeCallbackBody.code ==='1'){
                let code = await ym51.getSms();
                return {validateCode,header, code, tel};
            } else {
                await sleep(2);
                return await getValidateCode(tel);
            }
        } else {
            await sleep(2);
            return await getValidateCode(tel);
        }
    }catch(e){
        console.error(e);
        await sleep(2);
        return await getValidateCode(tel);
    } finally {
        fs.unlinkSync(pngPath)
    }
};
const regZhima = async()=>{
    const zhima = new mongo(db, 'backend.zhima.account');
    let validate = await getValidateCode();
    let name = random_name().replace(/\s/g, "");
    let password = randomString();
    let jsonCallback = `jQuery${randomString()}_${new Date().getTime()}`;
    let telCode = await request.get(`http://web.http.cnapi.cc/index/users/reg_do?jsonpcallback=${jsonCallback}&reg_name=${name}&password=${password}&re_password=${password}&verfy=${validate.validateCode}&phone=${validate.tel}&phone_code=${validate.code}&origin_tail=&expandsecret=&_=${new Date().getTime()}`).set(validate.header);
    let reg = new RegExp(`^${jsonCallback}\\("(\\S+)"\\)$`);
    let telCodeCallbackBody = telCode.text.match(reg) ? JSON.parse(telCode.text.match(reg)[1].replace(/\\"/g,"\"")) : {};
    console.log('telCodeCallbackBody', validate.tel, telCodeCallbackBody.msg);
    if(telCodeCallbackBody.code === "1"){
        await zhima.update({tel:validate.tel},{$set:{password, name ,created_at:new Date()}});
    }
};
const getOne = ()=>{
    return new Promise(async (resolve, reject) => {
        process.stdout.write(`***************************说明***********************************************\n`);
        process.stdout.write(`* 1. 注册芝麻软件账户 \n`);
        process.stdout.write(`***************************结束***********************************************\n`);
        process.stdout.write(`\n`);
        process.stdout.write(`\n`);
        process.stdout.write(`请输入指令\n`);
        process.stdin.resume();
        process.stdin.setEncoding('utf-8');
        process.stdin.once('data', async (chunk) => {
            try{
                chunk = chunk.replace(/(\n|\r|\s)/g, '');
                switch(chunk){
                    case "":
                        break;
                    case "1":
                        await regZhima();
                        break;
                }
                await getOne();
            }catch(e){
                console.error(e);
                await getOne();
            }
        });
    });
};
MongoClient.connect(`mongodb://vino:3623@${ip}/proxy_serve`,{poolSize:1,autoReconnect:true}, async function (err, db) {
    if(err){
        console.error("proxy server error" , err)
    } else {
        global.db = db.db('proxy_serve');
        await getOne();
    }
});